#ifndef BINLOG_MANAGER_H
#define BINLOG_MANAGER_H

#include "../../include/gudb.h"
#include "../transaction/transaction_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include <time.h>

// MySQL binlog constants
#define BINLOG_MAGIC            "\xfe\x62\x69\x6e"  // MySQL binlog magic number
#define BINLOG_VERSION          4                    // MySQL binlog version
#define BINLOG_HEADER_SIZE      19                   // Standard event header size
#define BINLOG_CHECKSUM_SIZE    4                    // CRC32 checksum size
#define BINLOG_MAX_EVENT_SIZE   (16 * 1024 * 1024)  // 16MB max event size
#define BINLOG_FILE_SIZE        (1024 * 1024 * 1024) // 1GB per binlog file

// Forward declarations
typedef struct binlog_manager binlog_manager_t;
typedef struct binlog_file binlog_file_t;
typedef struct binlog_event binlog_event_t;
typedef struct binlog_reader binlog_reader_t;
typedef struct gtid_set gtid_set_t;

// MySQL-compatible event types
typedef enum {
    UNKNOWN_EVENT = 0,
    START_EVENT_V3 = 1,
    QUERY_EVENT = 2,
    STOP_EVENT = 3,
    ROTATE_EVENT = 4,
    INTVAR_EVENT = 5,
    LOAD_EVENT = 6,
    SLAVE_EVENT = 7,
    CREATE_FILE_EVENT = 8,
    APPEND_BLOCK_EVENT = 9,
    EXEC_LOAD_EVENT = 10,
    DELETE_FILE_EVENT = 11,
    NEW_LOAD_EVENT = 12,
    RAND_EVENT = 13,
    USER_VAR_EVENT = 14,
    FORMAT_DESCRIPTION_EVENT = 15,
    XID_EVENT = 16,
    BEGIN_LOAD_QUERY_EVENT = 17,
    EXECUTE_LOAD_QUERY_EVENT = 18,
    TABLE_MAP_EVENT = 19,
    PRE_GA_WRITE_ROWS_EVENT = 20,
    PRE_GA_UPDATE_ROWS_EVENT = 21,
    PRE_GA_DELETE_ROWS_EVENT = 22,
    WRITE_ROWS_EVENT_V1 = 23,
    UPDATE_ROWS_EVENT_V1 = 24,
    DELETE_ROWS_EVENT_V1 = 25,
    INCIDENT_EVENT = 26,
    HEARTBEAT_LOG_EVENT = 27,
    IGNORABLE_LOG_EVENT = 28,
    ROWS_QUERY_LOG_EVENT = 29,
    WRITE_ROWS_EVENT = 30,
    UPDATE_ROWS_EVENT = 31,
    DELETE_ROWS_EVENT = 32,
    GTID_LOG_EVENT = 33,
    ANONYMOUS_GTID_LOG_EVENT = 34,
    PREVIOUS_GTIDS_LOG_EVENT = 35
} binlog_event_type_t;

// Event flags
typedef enum {
    LOG_EVENT_BINLOG_IN_USE_F = 0x1,
    LOG_EVENT_FORCED_ROTATE_F = 0x2,
    LOG_EVENT_THREAD_SPECIFIC_F = 0x4,
    LOG_EVENT_SUPPRESS_USE_F = 0x8,
    LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F = 0x10,
    LOG_EVENT_ARTIFICIAL_F = 0x20,
    LOG_EVENT_RELAY_LOG_F = 0x40,
    LOG_EVENT_IGNORABLE_F = 0x80,
    LOG_EVENT_NO_FILTER_F = 0x100,
    LOG_EVENT_MTS_ISOLATE_F = 0x200
} binlog_event_flags_t;

// GTID (Global Transaction Identifier)
typedef struct {
    char server_uuid[37];       // UUID string format
    uint64_t transaction_id;    // Transaction sequence number
} gtid_t;

// GTID Set for tracking executed transactions
struct gtid_set {
    gtid_t* gtids;              // Array of GTIDs
    uint32_t count;             // Number of GTIDs
    uint32_t capacity;          // Array capacity
    pthread_mutex_t mutex;      // Protects GTID set
};

// Binlog event header (MySQL compatible)
typedef struct {
    uint32_t timestamp;         // Event timestamp
    uint8_t type_code;          // Event type
    uint32_t server_id;         // Server ID
    uint32_t event_length;      // Total event length
    uint32_t next_position;     // Position of next event
    uint16_t flags;             // Event flags
} binlog_event_header_t;

// Binlog event structure
struct binlog_event {
    binlog_event_header_t header;  // Standard header
    void* data;                    // Event-specific data
    uint32_t data_size;            // Size of event data
    uint32_t checksum;             // CRC32 checksum
    
    // Internal fields
    bool owns_data;                // Whether this event owns the data
    struct binlog_event* next;     // For free list
};

// Query event data
typedef struct {
    uint32_t thread_id;            // Thread ID
    uint32_t exec_time;            // Execution time
    uint8_t db_name_len;           // Database name length
    uint16_t error_code;           // Error code
    uint16_t status_vars_len;      // Status variables length
    char* db_name;                 // Database name
    char* query;                   // SQL query
    uint32_t query_len;            // Query length
} query_event_data_t;

// XID event data (transaction commit)
typedef struct {
    uint64_t xid;                  // Transaction ID
} xid_event_data_t;

// Table map event data
typedef struct {
    uint64_t table_id;             // Table ID
    uint16_t flags;                // Table flags
    uint8_t db_name_len;           // Database name length
    char* db_name;                 // Database name
    uint8_t table_name_len;        // Table name length
    char* table_name;              // Table name
    uint32_t column_count;         // Number of columns
    uint8_t* column_types;         // Column type array
    uint32_t column_metadata_len;  // Metadata length
    uint8_t* column_metadata;      // Column metadata
    uint8_t* null_bits;            // Null bit array
} table_map_event_data_t;

// Row event data (for INSERT/UPDATE/DELETE)
typedef struct {
    uint64_t table_id;             // Table ID
    uint16_t flags;                // Row flags
    uint32_t column_count;         // Number of columns
    uint8_t* columns_before_image;  // Columns in before image
    uint8_t* columns_after_image;   // Columns in after image
    void* row_data;                // Actual row data
    uint32_t row_data_size;        // Size of row data
} rows_event_data_t;

// GTID event data
typedef struct {
    uint8_t flags;                 // GTID flags
    char server_uuid[16];          // Server UUID (binary)
    uint64_t transaction_id;       // Transaction ID
    uint8_t logical_clock_type;    // Logical clock type
    uint64_t logical_clock;        // Logical clock value
} gtid_event_data_t;

// Format description event data
typedef struct {
    uint16_t binlog_version;       // Binlog format version
    char server_version[50];       // Server version string
    uint32_t create_timestamp;     // Creation timestamp
    uint8_t common_header_len;     // Common header length
    uint8_t* post_header_len;      // Post-header lengths array
    uint8_t checksum_alg;          // Checksum algorithm
} format_desc_event_data_t;

// Binlog file structure
struct binlog_file {
    char* filename;                // File path
    int fd;                        // File descriptor
    uint64_t size;                 // Current file size
    uint64_t position;             // Current write position
    uint32_t sequence;             // File sequence number
    
    bool is_active;                // Whether this is the active file
    bool needs_sync;               // Whether file needs fsync
    time_t created_time;           // File creation time
    
    pthread_mutex_t mutex;         // File-level mutex
    struct binlog_file* next;      // Next file in list
};

// Binlog reader for reading events
struct binlog_reader {
    binlog_file_t* current_file;   // Current file being read
    uint64_t position;             // Current read position
    char* filename_pattern;        // Filename pattern
    uint32_t start_sequence;       // Starting file sequence
    
    // Read buffer
    char* buffer;                  // Read buffer
    uint32_t buffer_size;          // Buffer size
    uint32_t buffer_used;          // Bytes used in buffer
    uint32_t buffer_pos;           // Current position in buffer
    
    // State
    bool at_end;                   // Whether at end of logs
    gtid_set_t* executed_gtids;    // Executed GTID set
};

// Binlog manager - main coordinator
struct binlog_manager {
    // Configuration
    char* binlog_directory;        // Binlog files directory
    char* filename_prefix;         // Filename prefix
    uint64_t max_file_size;        // Maximum file size
    uint32_t server_id;            // MySQL server ID
    char server_uuid[37];          // Server UUID
    bool sync_binlog;              // Whether to sync after each event
    uint32_t expire_logs_days;     // Days to keep old logs
    
    // Current state
    binlog_file_t* active_file;    // Currently active file
    binlog_file_t* files;          // List of all files
    uint32_t next_sequence;        // Next file sequence number
    uint64_t next_position;        // Next write position
    
    // GTID management
    gtid_set_t* executed_gtids;    // All executed GTIDs
    uint64_t next_transaction_id;  // Next transaction ID to assign
    
    // Synchronization
    pthread_mutex_t manager_mutex; // Protects manager state
    pthread_rwlock_t files_lock;   // Protects file list
    
    // Background maintenance
    pthread_t maintenance_thread;  // Background maintenance
    bool maintenance_running;      // Whether maintenance is running
    pthread_mutex_t maintenance_mutex;
    pthread_cond_t maintenance_cond;
    
    // Statistics
    uint64_t events_written;       // Total events written
    uint64_t bytes_written;        // Total bytes written
    uint64_t files_created;        // Number of files created
    uint64_t files_rotated;        // Number of file rotations
    uint64_t sync_count;           // Number of syncs performed
    
    // Event cache for replication
    binlog_event_t** event_cache;  // LRU cache of recent events
    uint32_t cache_size;           // Cache size
    uint32_t cache_used;           // Cache entries used
    pthread_mutex_t cache_mutex;   // Cache protection
};

// Main Binlog Manager API

// Lifecycle management
binlog_manager_t* binlog_manager_create(const char* binlog_dir, const char* prefix, 
                                       uint32_t server_id);
void binlog_manager_destroy(binlog_manager_t* binlog);
int binlog_manager_start(binlog_manager_t* binlog);
int binlog_manager_stop(binlog_manager_t* binlog);

// Configuration
int binlog_set_max_file_size(binlog_manager_t* binlog, uint64_t size);
int binlog_set_server_id(binlog_manager_t* binlog, uint32_t server_id);
int binlog_set_server_uuid(binlog_manager_t* binlog, const char* uuid);
int binlog_set_sync_mode(binlog_manager_t* binlog, bool sync_enabled);
int binlog_set_expire_days(binlog_manager_t* binlog, uint32_t days);

// Event logging
int binlog_write_query_event(binlog_manager_t* binlog, uint32_t thread_id,
                             const char* db_name, const char* query,
                             uint32_t exec_time, uint16_t error_code);
int binlog_write_xid_event(binlog_manager_t* binlog, uint64_t xid);
int binlog_write_gtid_event(binlog_manager_t* binlog, const gtid_t* gtid);
int binlog_write_table_map_event(binlog_manager_t* binlog, uint64_t table_id,
                                 const char* db_name, const char* table_name,
                                 uint32_t column_count, uint8_t* column_types);
int binlog_write_rows_event(binlog_manager_t* binlog, binlog_event_type_t event_type,
                           uint64_t table_id, uint32_t column_count,
                           void* row_data, uint32_t data_size);

// File management
int binlog_rotate_file(binlog_manager_t* binlog);
int binlog_purge_old_files(binlog_manager_t* binlog, time_t before_time);
binlog_file_t* binlog_get_file_list(binlog_manager_t* binlog);

// Reading and replication
binlog_reader_t* binlog_reader_create(const char* binlog_dir, const char* prefix,
                                     uint32_t start_sequence, uint64_t start_position);
void binlog_reader_destroy(binlog_reader_t* reader);
binlog_event_t* binlog_reader_next_event(binlog_reader_t* reader);
int binlog_reader_seek_to_gtid(binlog_reader_t* reader, const gtid_t* gtid);

// Event management
binlog_event_t* binlog_event_create(binlog_event_type_t type, void* data, uint32_t data_size);
void binlog_event_destroy(binlog_event_t* event);
binlog_event_t* binlog_event_copy(binlog_event_t* event);
uint32_t binlog_event_calculate_checksum(binlog_event_t* event);

// GTID management
gtid_set_t* gtid_set_create(void);
void gtid_set_destroy(gtid_set_t* set);
int gtid_set_add(gtid_set_t* set, const gtid_t* gtid);
bool gtid_set_contains(gtid_set_t* set, const gtid_t* gtid);
char* gtid_set_to_string(gtid_set_t* set);
gtid_set_t* gtid_set_from_string(const char* gtid_string);

// Utility functions
const char* binlog_event_type_to_string(binlog_event_type_t type);
uint32_t binlog_calculate_crc32(const void* data, uint32_t size);
int binlog_parse_filename(const char* filename, uint32_t* sequence);
char* binlog_generate_filename(const char* prefix, uint32_t sequence);

// Statistics and monitoring
void binlog_manager_print_stats(binlog_manager_t* binlog);
uint64_t binlog_get_total_size(binlog_manager_t* binlog);
uint32_t binlog_get_file_count(binlog_manager_t* binlog);
binlog_event_t* binlog_get_last_event(binlog_manager_t* binlog);

// Replication support
int binlog_register_slave(binlog_manager_t* binlog, uint32_t slave_server_id);
int binlog_unregister_slave(binlog_manager_t* binlog, uint32_t slave_server_id);
int binlog_send_events_to_slave(binlog_manager_t* binlog, uint32_t slave_server_id,
                               uint64_t start_position, int socket_fd);

// Recovery and consistency
int binlog_verify_integrity(binlog_manager_t* binlog, const char* filename);
int binlog_repair_file(binlog_manager_t* binlog, const char* filename);
gtid_set_t* binlog_get_executed_gtids(binlog_manager_t* binlog);

// Format description and compatibility
int binlog_write_format_desc_event(binlog_manager_t* binlog);
int binlog_write_rotate_event(binlog_manager_t* binlog, const char* next_filename);
bool binlog_is_mysql_compatible(binlog_manager_t* binlog);

// Background maintenance
void* binlog_maintenance_thread_func(void* arg);

// Internal helper functions
static int write_event_to_file(binlog_file_t* file, binlog_event_t* event);
static binlog_event_t* read_event_from_file(binlog_file_t* file, uint64_t position);
static int create_new_binlog_file(binlog_manager_t* binlog);
static uint32_t assign_transaction_id(binlog_manager_t* binlog);

#endif // BINLOG_MANAGER_H